package minimax

import (
	"gitee.com/extrame/math/tools"
	"github.com/sirupsen/logrus"
)

var DefaultConfig = &Config{
	RelError: true,
	Pin:      false,
	OrderN:   6,
	OrderD:   0,
	// TargetPrecision:  64, //boost::math::tools::digits<long double>
	WorkingPercision: 128,
	Brake:            50,
}

type Config struct {
	// A        float64
	// B        float64
	Ranges   [][3]float64
	RangeLen float64
	RelError bool
	Pin      bool
	OrderN   int
	OrderD   int
	// TargetPrecision  uint
	WorkingPercision uint
	// Variant          int //函数种类
	Skew  int
	Brake int
}

func (c *Config) SetOrderN(n int) *Config {
	c.OrderN = n
	return c
}

func (c *Config) SetPin(pin bool) *Config {
	c.Pin = pin
	return c
}

func (c *Config) Point(angle float64) float64 {
	distance := angle * c.RangeLen
	for _, ra := range c.Ranges {
		if ra[2] >= distance {
			return ra[0] + distance
		}
		distance -= ra[2]
	}
	return c.Ranges[0][0] + c.RangeLen
}

//add range ,a must lower than b
func (c *Config) AddRange(a, b float64) *Config {
	if a > b {
		logrus.Fatalln("a must lower than b")
	}
	c.Ranges = append(c.Ranges, [3]float64{a, b, b - a})
	c.RangeLen += b - a
	return c
}

func (c *Config) MaxOrder() int {
	if c.OrderD > c.OrderN {
		return c.OrderD
	}
	return c.OrderN
}

func (c *Config) OrderNWithPin() int {
	if c.Pin {
		return c.OrderN
	}
	return c.OrderN + 1
}

func (c *Config) Iter(i int) int {
	if c.Pin {
		return i + 1
	}
	return i
}

func (c *Config) Run(fn Fn) (tools.Poly, tools.Poly) {
	var minimax = Minimax{}
	minimax.Set(c, fn)
	for i := 0; i < 20; i++ {
		var result = minimax.Iter()
		if result < 0.01 {
			break
		}
	}
	return minimax.Numerator(), minimax.Denominator()
}
